local Widget = require "widgets/widget"
local UIAnim  = require "widgets/uianim"
local Text = require "widgets/text" -- 引入 Text 控件库
local Image = require "widgets/image" -- 引入 Image 控件库
local ImageButton = require "widgets/imagebutton" -- 引入 ImageButton 控件库
local ScrollGridList = require("core_ShadowFieldExciter/widgets/ScrollGridList") -- 引入自定义的 ScrollGridList 控件库
local json = require "json" -- 引入 JSON 库，用于处理数据
local CheckBox = require("core_ShadowFieldExciter/widgets/CheckBox") -- 引入自定义的 CheckBox 控件库
local NamePresetScreen = require("core_ShadowFieldExciter/screens/NamePresetScreen") -- 引入自定义的 NamePresetScreen 控件库
local PopupDialogScreen = require("core_ShadowFieldExciter/screens/PopupDialogScreen") -- 引入自定义的 PopupDialogScreen 控件库
local sfe_presetdata_utils = require("core_ShadowFieldExciter/utils/sfe_presetdata_utils") -- 引入自定义的 sfe_presetdata_utils 模块

local db = TUNING.MOD_ShadowFieldExciter -- 获取模组的配置数据
local strings = STRINGS.MOD_ShadowFieldExciter -- 获取模组的本地化字符串

AddClassPostConstruct("widgets/containerwidget", function(self) -- 对 ContainerWidget 类进行后构造修改
    local _Open = self.Open -- 保存原始的 Open 方法
    local _Close = self.Close -- 保存原始的 Close 方法
    --local _Refresh = self.Refresh -- 保存原始的 Refresh 方法
    local _OnItemGet = self.OnItemGet -- 保存原始的 OnItemGet 方法

    self.custom_ui_elements = {} -- 初始化一个表来存储自定义添加的 UI 元素
    
    function self:Open(container, doer) -- 重写 Open 方法
        if container.prefab == db.Prefab_ID then -- 检查打开的容器是否是本模组的特定容器
            --防止多人一起设置
            
            if #container.replica.container.openers > 1 then -- 如果有超过一个玩家正在打开这个容器
                if doer and doer.components and doer.components.talker then -- 检查执行者是否存在且有 talker 组件
                    doer.components.talker:Say(strings.MSG_OpenTips) -- 让执行者说出提示信息（防止多人同时设置）
                end
                return -- 阻止打开 UI
            end
        end
        _Open(self, container, doer) -- 调用原始的 Open 方法
        self.custom_ui_elements = {} -- 清空之前可能存在的自定义 UI 元素，确保每次打开都是新的状态
        
        local widget = container.replica.container:GetWidget() or {} -- 获取容器的 widget 配置，如果不存在则使用空表
        --添加buttons的逻辑(实际上这个我没用上，但是还是留在这里吧)
        if widget.buttons then -- 如果 widget 配置中有 buttons 表
            for i, buttoninfo in ipairs(widget.buttons) do -- 遍历所有按钮配置
                local button = self:AddChild(ImageButton( -- 创建 ImageButton 实例并添加到当前 widget
                    buttoninfo.atlas or "images/ui.xml", -- 按钮图集路径，默认为 "images/ui.xml"
                    buttoninfo.image or "button_small.tex", -- 按钮正常状态纹理，默认为 "button_small.tex"
                    buttoninfo.image_over or "button_small_over.tex", -- 按钮悬停状态纹理，默认为 "button_small_over.tex"
                    buttoninfo.image_disabled or "button_small_disabled.tex" -- 按钮禁用状态纹理，默认为 "button_small_disabled.tex"
                ))
                
                -- 设置按钮属性...
                button.image:SetScale(buttoninfo.scale or 1.2) -- 设置按钮图片的缩放，默认为 1.2
                button.text:SetPosition(2, -2) -- 设置按钮文本的位置偏移
                button:SetPosition(buttoninfo.position or Vector3(0, 0, 0)) -- 设置按钮的位置，默认为 (0, 0, 0)
                button:SetText(buttoninfo.text or "") -- 设置按钮的文本内容，默认为空字符串

                -- 在按钮创建代码中添加：
                if buttoninfo.tooltip then -- 如果按钮配置中有 tooltip
                    -- 使用SetTooltip添加提示
                    button:SetTooltip(buttoninfo.tooltip) -- 设置按钮的悬停提示文本
                    -- 保持悬停音效
                    button:SetOnGainFocus(function() -- 设置按钮获得焦点时的回调
                        TheFrontEnd:GetSound():PlaySound("dontstarve/HUD/click_mouseover") -- 播放悬停音效
                    end)
                end
                
                if buttoninfo.fn then -- 如果按钮配置中有点击回调函数 fn
                    button:SetOnClick(function() -- 设置按钮的点击事件回调
                        if doer and (doer:HasTag("busy") or -- 检查执行者是否存在且是否处于 "busy" 状态
                           (doer.components.playercontroller and -- 或者执行者是否有玩家控制器组件
                            not doer.components.playercontroller:IsEnabled())) then -- 且玩家控制器是否被禁用
                            return -- 如果执行者忙碌或无法控制，则不执行回调
                        end
                        buttoninfo.fn(container, doer) -- 执行配置中定义的点击回调函数，传入容器和执行者
                    end)
                end
                
                button:SetFont(buttoninfo.font or BUTTONFONT) -- 设置按钮文本字体，默认为 BUTTONFONT
                button:SetDisabledFont(buttoninfo.disabled_font or BUTTONFONT) -- 设置按钮禁用状态下的文本字体，默认为 BUTTONFONT
                button:SetTextSize(buttoninfo.text_size or 33) -- 设置按钮文本大小，默认为 33
                button.text:SetVAlign(ANCHOR_MIDDLE) -- 设置按钮文本垂直居中对齐
                button.text:SetColour(unpack(buttoninfo.text_color or {0, 0, 0, 1})) -- 设置按钮文本颜色，默认为黑色
                
                if buttoninfo.validfn then -- 如果按钮配置中有有效性检查函数 validfn
                    if buttoninfo.validfn(container) then -- 调用有效性检查函数，传入容器
                        button:Enable() -- 如果有效，则启用按钮
                    else
                        button:Disable() -- 否则禁用按钮
                    end
                end
                
                if TheInput:ControllerAttached() then -- 如果连接了控制器
                    button:Hide() -- 隐藏按钮（通常控制器有不同的 UI 交互方式）
                end
                
                table.insert(self.custom_ui_elements, button) -- 将创建的按钮添加到自定义 UI 元素列表中，方便后续管理（如关闭时移除）
            end
        end
        --以下是自定义的模组物品widget逻辑
        if container.prefab == db.Prefab_ID then -- 再次检查，确保这是本模组的特定容器，开始添加模组专属 UI
            
            --得到对应的网络变量
            self.ServerGUID = container.GuidNet:value() -- 获取容器的网络变量 ServerGUID
            self.CollectRule = json.decode(container.CollectRuleNet:value()) -- 获取并解码收集规则的网络变量 CollectRuleNet
            self.CollectMode = json.decode(container.CollectModeNet:value()) -- 获取并解码收集模式的网络变量 CollectModeNet
            self.ItemWhiteList = json.decode(container.ItemWhiteListNet:value()) -- 获取并解码物品白名单的网络变量 ItemWhiteListNet
            self.ItemBlackList = json.decode(container.ItemBlackListNet:value()) -- 获取并解码物品黑名单的网络变量 ItemBlackListNet
            --print("客户端得到的主机端GUID是"..guid)
            -- 定义规则顺序
            local ruleKeys = {
                "IgnoreWeapon",
                "IgnoreArmor",
                "IgnoreAmulet",
                "IgnoreUnStackable",
                "IgnoreFood",
                "IgnoreSomething"
            }
            -- 定义模式顺序
            local modeKeys = {
                "MatchMode"
            }
            local ruleString = strings.CollectRule -- 获取收集规则的本地化字符串表
            local modeString = strings.CollectMode -- 获取收集模式的本地化字符串表
            -- 在函数开头声明这两个变量
            local WhiteGridList, BlackGridList, RuleGridList, ModeGridList, PresetList --  定义五个变量，用于存储白名单、黑名单、规则、模式和预设的网格列表

            --#region 辅助函数

            -- 浅拷贝函数
            local function ShallowCopy(original_table)
                if type(original_table) ~= "table" then
                    return original_table -- 如果不是表，直接返回原值
                end
                local copy = {}
                for key, value in pairs(original_table) do
                    copy[key] = value -- 复制键值对
                end
                return copy
            end

            --判断对应名单里面有没有对应的物品
            local function IsListHasItem(list, item_name)
                for index, value in ipairs(list) do -- 遍历列表
                    if value == item_name then -- 如果找到匹配的物品名
                        return true -- 返回 true
                    end
                end
                return false -- 遍历完成未找到，返回 false
            end

            --移除对应名单里面的对应物品 只针对名单表,不修改UI表现
            local function RemoveItemFromList(list, item_name)
                for i = #list, 1, -1 do -- 从后向前遍历列表，避免删除元素导致索引错乱
                    if list[i] == item_name then -- 如果找到匹配的物品名 --从后向前遍历，防止索引错位
                        table.remove(list, i) -- 从列表中移除该元素
                    end
                end
            end

            --添加对应物品到对应名单 只针对名单表,不修改UI表现
            local function AddItemToList(list,item_name)
                if list == self.ItemWhiteList then -- 如果目标列表是白名单 --判断list是否是ItemWhiteList的引用
                    RemoveItemFromList(self.ItemBlackList,item_name) -- 先尝试从黑名单中移除该物品 --先从黑名单中移除
                    
                    if not IsListHasItem(self.ItemWhiteList,item_name) then -- 如果白名单中尚不存在该物品 --白名单中没有就加上
                        table.insert(self.ItemWhiteList,item_name) -- 将物品添加到白名单
                    end
                elseif list == self.ItemBlackList then -- 如果目标列表是黑名单 --判断list是否是ItemBlackList的引用
                    RemoveItemFromList(self.ItemWhiteList,item_name) -- 先尝试从白名单中移除该物品 --先从白名单中移除
                    
                    if not IsListHasItem(self.ItemBlackList,item_name) then -- 如果黑名单中尚不存在该物品 --黑名单中没有就加上
                        table.insert(self.ItemBlackList,item_name) -- 将物品添加到黑名单
                    end
                end
            end

            -- 检查物品的图标和纹理
            local function CheckPrefabAtlasAndTex(prefab)
                if prefab == 'rock_avocado_fruit' then
                    return "images/inventoryimages2.xml","rock_avocado_fruit_rockhard.tex" -- 石果物品的图集和纹理
                end
            end

            -- 隐藏特殊图标背景,在打开时调用一次
            local function HideSpecialItemBg()
                if self.inv then
                    for k, v in pairs(self.inv) do
                        if v.tile then
                            if v.tile.bg then
                                v.tile.bg:Hide() -- 隐藏物品图标背景
                            end
                            if v.tile.spoilage then
                                v.tile.spoilage:Hide() -- 隐藏物品腐烂进度条
                            end
                            if v.tile.wetness then
                                v.tile.wetness:Hide() -- 隐藏物品潮湿进度条
                            end

                            if v.tile.rechargeframe then
                                v.tile.rechargeframe:Hide() -- 隐藏物品充能框架
                            end

                            if v.tile.recharge then
                                v.tile.recharge:Hide() -- 隐藏物品充能进度条
                            end
                        end
                    end
                end
            end

            -- 保存预设到本地存储
            local function SavePreset()
                sfe_presetdata_utils:Save(db.PresetData) -- 调用预设数据工具函数保存预设数据
            end

            -- 添加预设到db.PresetData （同时改变ui显示）
            local function AddPreset(name, description)
                db.PresetData = sfe_presetdata_utils:AddPreset(db.PresetData,{
                    version = db.DataVersion, -- 使用模组数据版本
                    name = name,
                    description = description,
                    CollectRule = ShallowCopy(self.CollectRule), -- 浅拷贝当前收集规则
                    CollectMode = ShallowCopy(self.CollectMode), -- 浅拷贝当前收集模式
                    ItemWhiteList = ShallowCopy(self.ItemWhiteList), -- 浅拷贝当前白名单
                    ItemBlackList = ShallowCopy(self.ItemBlackList), -- 浅拷贝当前黑名单
                }) -- 调用预设数据工具函数添加预设
                PresetList:ResetGrids(db.PresetData.list) -- 刷新预设列表显示
                SavePreset() -- 保存预设到本地存储
            end

            -- 从db.PresetData删除预设 （同时改变ui显示）
            local function RemovePreset(name)
                db.PresetData = sfe_presetdata_utils:RemovePreset(db.PresetData, name) -- 调用预设数据工具函数删除指定名称的预设
                PresetList:ResetGrids(db.PresetData.list) -- 刷新预设列表显示
                SavePreset() -- 保存预设到本地存储
            end

            -- 从db.PresetData加载预设到配置
            local function LoadPreset(name)
                local preset = db.PresetData.list[name] -- 从预设数据中获取指定名称的预设
                if preset then -- 如果找到了预设
                    self.CollectRule = ShallowCopy(preset.CollectRule) -- 浅拷贝收集规则
                    self.CollectMode = ShallowCopy(preset.CollectMode) -- 浅拷贝收集模式
                    self.ItemWhiteList = ShallowCopy(preset.ItemWhiteList) -- 浅拷贝白名单
                    self.ItemBlackList = ShallowCopy(preset.ItemBlackList) -- 浅拷贝黑名单
                    RuleGridList:ResetGrids(self.CollectRule) -- 刷新规则网格显示
                    ModeGridList:ResetGrids(self.CollectMode) -- 刷新模式网格显示
                    WhiteGridList:ResetGrids(self.ItemWhiteList) -- 刷新白名单网格显示
                    BlackGridList:ResetGrids(self.ItemBlackList) -- 刷新黑名单网格显示
                end
            end

            --#endregion

            --白名单Title
            local whiteList_text = Text(strings.Title_Font,strings.Title_Font_Size) -- 创建一个 Text 控件用于显示白名单标题
            --#region相关设置
            whiteList_text:SetString(STRINGS.MOD_ShadowFieldExciter.Lab_WhiteList) -- 设置标题文本内容（从本地化字符串获取）
            whiteList_text:SetColour(1,1,1,1) -- 设置标题文本颜色为白色
            whiteList_text:SetPosition(165,210,0) -- 设置标题位置
            whiteList_text:SetVAlign(ANCHOR_MIDDLE) -- 设置垂直对齐方式为居中
            whiteList_text:SetHAlign(ANCHOR_MIDDLE) -- 设置水平对齐方式为居中
            self:AddChild(whiteList_text) -- 将标题控件添加到父控件
            table.insert(self.custom_ui_elements,whiteList_text) -- 将标题控件添加到自定义 UI 元素列表
            --#endregion

            --黑名单Title
            local blackList_text = Text(strings.Title_Font,strings.Title_Font_Size) -- 创建一个 Text 控件用于显示黑名单标题
            --#region相关设置
            blackList_text:SetString(STRINGS.MOD_ShadowFieldExciter.Lab_BlackList) -- 设置标题文本内容（从本地化字符串获取）
            blackList_text:SetColour(0.5, 0.5, 0.5, 1) -- 设置标题文本颜色为灰色
            blackList_text:SetPosition(-172,210,0) -- 设置标题位置
            blackList_text:SetVAlign(ANCHOR_MIDDLE) -- 设置垂直对齐方式为居中
            blackList_text:SetHAlign(ANCHOR_MIDDLE) -- 设置水平对齐方式为居中
            self:AddChild(blackList_text) -- 将标题控件添加到父控件
            table.insert(self.custom_ui_elements,blackList_text) -- 将标题控件添加到自定义 UI 元素列表
            --#endregion


            --#region添加白名单滑动网格
            WhiteGridList = self:AddChild(ScrollGridList( -- 创建并添加白名单的滚动网格列表控件
                self.ItemWhiteList, -- 初始数据源为白名单列表
                function (item_names) -- 数据转换函数，将物品名转换为网格项所需的数据结构
                    local items = {} -- 初始化一个空表用于存储转换后的物品数据
                    for _, item_name in ipairs(item_names) do
                        
                        local atlas, tex = CheckPrefabAtlasAndTex(item_name) -- 检查物品的图集和纹理
                        --print(item_name.."的图集路径（白名单）:"..tostring(atlas)) -- 调试输出物品图集路径

                        table.insert(items,{ -- 将物品数据添加到列表中
                            prefab = item_name, -- 保存物品的 prefab 名称
                            tex = tex or item_name..".tex",  -- 物品图标纹理
                            atlas = atlas or GetInventoryItemAtlas(item_name..".tex") or "images/inventoryimages2.xml", -- 物品图标图集
                            normal =tex or item_name..".tex", -- 正常状态显示的纹理
                            focus = tex or item_name..".tex", -- 鼠标悬停（焦点）状态显示的纹理
                            tooltip = STRINGS.NAMES[string.upper(item_name)] or item_name, -- 物品的悬停提示文本（优先使用游戏内名称，否则用 prefab 名）
                            onclick = function (prefab) -- 点击事件处理函数
                                print("点击白名单物品:", prefab) -- 调试输出
                                -- 左键：将物品从白名单移到黑名单
                                AddItemToList(self.ItemBlackList, prefab) -- 调用辅助函数将物品添加到黑名单
                                -- 刷新两个列表显示
                                WhiteGridList:ResetGrids(self.ItemWhiteList) -- 更新白名单网格显示
                                BlackGridList:ResetGrids(self.ItemBlackList) -- 更新黑名单网格显示
                            end,
                            onrightclick = function(prefab) -- 右键点击事件回调
                            print("右键点击白名单物品:", prefab) -- 调试输出
                            -- 右键：从白名单中移除物品
                            RemoveItemFromList(self.ItemWhiteList, prefab) -- 调用辅助函数从白名单移除物品
                            -- 刷新列表显示
                            WhiteGridList:ResetGrids(self.ItemWhiteList) -- 更新白名单网格显示
                            end
                        })
                    end
                    return items -- 返回转换后的物品数据列表
                end,
                { -- 网格列表的配置选项
                    grid_width = 63, -- 每个网格单元的宽度
                    grid_height = 63, -- 每个网格单元的高度
                    spacing = 0, -- 网格单元之间的间距
                    rows =  5, -- 网格的行数
                    columns = 4, -- 网格的列数
                    peek_height = 0, -- 预览高度（不预览）
                    end_offset = 1, -- 结束偏移量（默认为 1）
                    scissor_pad = 10, -- 水平裁剪填充（默认为 10）
                    item_ctor_fn = function (context, index) -- 网格项构造函数，用于创建每个单元格的 UI 元素
                        local imgbtn = ImageButton() -- 创建一个 ImageButton 作为单元格的基础
                        return imgbtn -- 返回创建的 ImageButton
                    end,
                    apply_fn = function (ontext, imgbtn, item, index) -- 网格项应用函数，用于将数据应用到单元格 UI 元素上
                        if item then -- 如果当前单元格有对应的数据项
                            -- 设置物品图标
                            imgbtn:SetTextures(item.atlas, item.normal,item.focus) -- 设置 ImageButton 的纹理（图集、正常、悬停）
                            
                            imgbtn:SetTooltip(item.tooltip) -- 设置 ImageButton 的悬停提示
                            -- 左键点击事件
                            imgbtn:SetOnClick(function() -- 设置 ImageButton 的左键点击回调
                                if item.onclick then item.onclick(item.prefab) end -- 如果数据项中有 onclick 回调，则执行它
                            end)
                            
                            -- 右键点击事件 - 使用OnControl替代SetRightClick
                            local old_OnControl = imgbtn.OnControl -- 保存原始的 OnControl 方法
                            imgbtn.OnControl = function(self, control, down) -- 重写 OnControl 方法来处理右键点击
                                if control == CONTROL_SECONDARY and down and item.onrightclick then -- 如果是鼠标右键按下 (CONTROL_SECONDARY) 且数据项中有 onrightclick 回调 --处理右键点击事件
                                    item.onrightclick(item.prefab) -- 执行数据项中的 onrightclick 回调
                                    return true -- 返回 true 表示事件已处理
                                end
                                return old_OnControl(self, control, down) -- 否则调用原始的 OnControl 方法处理其他控制事件
                            end
                            
                            imgbtn:Show() -- 显示 ImageButton
                        else
                            imgbtn:Hide() -- 如果没有数据项，则隐藏 ImageButton
                        end
                    end,
                    scrollbar_offset = 30, -- 设置滚动条的水平偏移量，默认为30
                    scrollbar_vertical_offset = 0, -- 设置滚动条的垂直偏移量，默认为0
                    scrollbar_height_offset = -20, -- 设置滚动条的高度的变化值，默认-60(相对于滚动列表的高度减少-60)
                    scrollbar_style = -- 滚动条样式配置
                    {
                        atlas = "images/my_futuristic_ui/my_futuristic_ui.xml", -- 滚动条使用的图集
                        up_arrow = "white_scrollbar_arrow_up.tex", -- 向上箭头纹理
                        up_arrow_scale = 0.18, -- 向上箭头缩放比例
                        down_arrow = "white_scrollbar_arrow_down.tex", -- 向下箭头纹理
                        down_arrow_scale = 0.18, -- 向下箭头缩放比例
                        bar = "white_scrollbar_bar.tex", -- 滚动条背景条纹理
                        bar_width = 20, -- 滚动条背景条宽度
                        bar_height = 260, -- 滚动条背景条高度
                        handle = "white_scrollbar_handle.tex", -- 滚动条滑块纹理
                        handle_scale = 0.25, -- 滑块缩放比例
                    }
                }))
                WhiteGridList:SetPosition(165, -28)  -- 设置白名单网格列表的位置 -- 调整位置
                table.insert(self.custom_ui_elements,WhiteGridList) -- 将白名单网格列表添加到自定义 UI 元素列表
                --#endregion

            --#region添加黑名单滑动网格
            BlackGridList = self:AddChild(ScrollGridList( -- 创建并添加黑名单的滚动网格列表控件
            self.ItemBlackList, -- 初始数据源为黑名单列表
            function (item_names) -- 数据转换函数，与白名单类似
                local items = {} -- 初始化一个空表用于存储转换后的物品数据
                for _, item_name in ipairs(item_names) do
                    local atlas, tex = CheckPrefabAtlasAndTex(item_name) -- 检查物品的图集和纹理
                    --print(item_name.."的图集路径（白名单）:"..tostring(atlas)) -- 调试输出物品图集路径
                    table.insert(items,{ -- 将物品数据添加到列表中
                        prefab = item_name, -- 保存物品的 prefab 名称
                        tex = tex or item_name..".tex",  -- 物品图标纹理
                        atlas = atlas or GetInventoryItemAtlas(item_name..".tex") or "images/inventoryimages2.xml", -- 物品图标图集
                        normal = tex or item_name..".tex", -- 正常状态显示的纹理
                        focus = tex or item_name..".tex", -- 鼠标悬停（焦点）状态显示的纹理
                        tooltip = STRINGS.NAMES[string.upper(item_name)] or item_name, -- 物品的悬停提示文本（优先使用游戏内名称，否则用 prefab 名）
                        onclick = function (prefab) -- 点击事件处理函数
                            print("点击黑名单物品:", prefab) -- 调试输出
                            -- 左键：将物品从黑名单移到白名单
                            AddItemToList(self.ItemWhiteList, prefab) -- 调用辅助函数将物品添加到白名单
                            -- 刷新两个列表显示
                            WhiteGridList:ResetGrids(self.ItemWhiteList) -- 更新白名单网格显示
                            BlackGridList:ResetGrids(self.ItemBlackList) -- 更新黑名单网格显示
                        end,
                        onrightclick = function(prefab) -- 右键点击事件回调
                            print("右键点击黑名单物品:", prefab) -- 调试输出
                            -- 右键：从黑名单中移除物品
                            RemoveItemFromList(self.ItemBlackList, prefab) -- 调用辅助函数从黑名单移除物品
                            -- 刷新列表显示
                            WhiteGridList:ResetGrids(self.ItemWhiteList) -- 更新白名单网格显示
                            BlackGridList:ResetGrids(self.ItemBlackList) -- 更新黑名单网格显示
                        end
                    })
                end
                return items -- 返回转换后的物品数据列表
            end,
            { -- 网格列表的配置选项，与白名单相同
                grid_width = 64, -- 每个网格单元的宽度
                grid_height = 63, -- 每个网格单元的高度
                spacing = 0, -- 网格单元之间的间距
                rows =  5, -- 网格的行数
                columns = 4, -- 网格的列数
                peek_height = 0, -- 预览高度（不预览）
                end_offset = 1, -- 结束偏移量（默认为 1）
                scissor_pad = 10, -- 水平裁剪填充（默认为 10）
                item_ctor_fn = function (context, index) -- 网格项构造函数
                    local imgbtn = ImageButton() -- 创建 ImageButton
                    return imgbtn -- 返回 ImageButton
                end,
                apply_fn = function (ontext, imgbtn, item, index) -- 网格项应用函数
                    if item then -- 如果有数据项
                        -- 设置物品图标
                        imgbtn:SetTextures(item.atlas, item.normal,item.focus) -- 设置纹理
                        
                        imgbtn:SetTooltip(item.tooltip) -- 设置悬停提示
                        -- 左键点击事件
                        imgbtn:SetOnClick(function() -- 设置左键点击回调
                            if item.onclick then item.onclick(item.prefab) end -- 执行数据项的 onclick
                        end)
                        
                        -- 右键点击事件 - 使用OnControl替代SetRightClick
                        local old_OnControl = imgbtn.OnControl -- 保存原始 OnControl
                        imgbtn.OnControl = function(self, control, down) -- 重写 OnControl
                            if control == CONTROL_SECONDARY and down and item.onrightclick then -- 如果是右键按下且有回调 --处理右键点击事件
                                item.onrightclick(item.prefab) -- 执行数据项的 onrightclick
                                return true -- 事件已处理
                            end
                            return old_OnControl(self, control, down) -- 调用原始 OnControl
                        end
                        
                        imgbtn:Show() -- 显示按钮
                    else
                        imgbtn:Hide() -- 隐藏按钮
                    end
                end,
                scrollbar_offset = 30, -- 设置滚动条的水平偏移量，默认为30
                scrollbar_vertical_offset = 0, -- 设置滚动条的垂直偏移量，默认为0
                scrollbar_height_offset = -20, -- 设置滚动条的高度的变化值，默认-60(相对于滚动列表的高度减少-60)                
                scrollbar_style = -- 滚动条样式配置，与白名单相同
                {
                    atlas = "images/my_futuristic_ui/my_futuristic_ui.xml", -- 图集
                    up_arrow = "black_scrollbar_arrow_up.tex", -- 上箭头
                    up_arrow_scale = 0.19, -- 上箭头缩放比例
                    down_arrow = "black_scrollbar_arrow_down.tex", -- 下箭头
                    down_arrow_scale = 0.19, -- 下箭头缩放比例
                    bar = "black_scrollbar_bar.tex", -- 背景条
                    bar_width = 20, -- 滚动条背景条宽度
                    bar_height = 260, -- 滚动条背景条高度
                    handle = "black_scrollbar_handle.tex", -- 滑块
                    handle_scale = 0.25, -- 滑块缩放比例
                }
            }))
            BlackGridList:SetPosition(-172, -28)  -- 设置黑名单网格列表的位置 -- 调整位置
            table.insert(self.custom_ui_elements,BlackGridList) -- 将黑名单网格列表添加到自定义 UI 元素列表
            --#endregion

            --#region添加白名单的按钮
            local AddItemWhiteListBtn = ImageButton("images/my_futuristic_ui/my_futuristic_ui.xml","white_plus_button_normal.tex","white_plus_button_hover.tex","white_plus_button_disabled.tex","white_plus_button_down.tex") -- 创建一个 ImageButton 用于将容器内物品添加到白名单
            AddItemWhiteListBtn:SetHoverText(strings.Btn_AddWhiteList_ToolTip,{ -- 设置按钮的悬停提示文本
                font = strings.Hover_Text_Font, -- 提示文本字体
                font_size = strings.Hover_Text_Font_Size, -- 提示文本字体大小
                offset_x = 0, -- 提示文本水平偏移
                offset_y = 60, -- 提示文本垂直偏移
                colour = {1,1,1,1}, -- 提示文本颜色（白色）
            })
            AddItemWhiteListBtn:SetOnClick(function () -- 设置按钮的点击事件回调
                --将槽位里面的物品加入白名单
                local items = self.container.replica.container:GetItems() -- 获取当前容器内的所有物品
                for k, item in pairs(items) do -- 遍历容器内的物品
                    AddItemToList(self.ItemWhiteList,item.prefab) -- 调用辅助函数将每个物品添加到白名单
                end
                WhiteGridList:ResetGrids(self.ItemWhiteList) -- 刷新白名单网格的 UI 显示
                BlackGridList:ResetGrids(self.ItemBlackList) -- 刷新黑名单网格的 UI 显示（因为添加白名单会移除黑名单中的对应项）

                -- 将物品返还给玩家
                if container and self.ServerGUID and doer and doer.userid then -- 检查容器、服务器 GUID、执行者和执行者用户 ID 是否都有效
                    SendModRPCToServer(MOD_RPC[db.Prefab_ID]["ReturnItemsToPlayer"], self.ServerGUID) -- 发送 RPC 请求到服务器，要求将容器内的物品返还给玩家
                end
            end)
            AddItemWhiteListBtn:SetPosition(-365,-150) -- 设置按钮的位置
            self:AddChild(AddItemWhiteListBtn) -- 将按钮添加到父控件
            table.insert(self.custom_ui_elements,AddItemWhiteListBtn) -- 将按钮添加到自定义 UI 元素列表
            --#endregion

            --#region添加黑名单的按钮
            local AddItemBlackListBtn = ImageButton("images/my_futuristic_ui/my_futuristic_ui.xml","black_plus_button_normal.tex","black_plus_button_hover.tex","black_plus_button_disabled.tex","black_plus_button_down.tex") -- 创建一个 ImageButton 用于将容器内物品添加到黑名单
            AddItemBlackListBtn:SetHoverText(strings.Btn_AddBlackList_ToolTip,{ -- 设置按钮的悬停提示文本
                font = strings.Hover_Text_Font, -- 提示文本字体
                font_size = strings.Hover_Text_Font_Size, -- 提示文本字体大小
                offset_x = 0, -- 提示文本水平偏移
                offset_y = 60, -- 提示文本垂直偏移
                colour = {1,1,1,1}, -- 提示文本颜色（白色）
            })
            AddItemBlackListBtn:SetOnClick(function () -- 设置按钮的点击事件回调
                --将槽位里面的物品加入黑名单
                local items = self.container.replica.container:GetItems() -- 获取当前容器内的所有物品
                for k, item in pairs(items) do -- 遍历容器内的物品
                    AddItemToList(self.ItemBlackList,item.prefab) -- 调用辅助函数将每个物品添加到黑名单
                end
                WhiteGridList:ResetGrids(self.ItemWhiteList) -- 刷新白名单网格的 UI 显示（因为添加黑名单会移除白名单中的对应项）
                BlackGridList:ResetGrids(self.ItemBlackList) -- 刷新黑名单网格的 UI 显示

                -- 将物品返还给玩家
                if container and self.ServerGUID and doer and doer.userid then -- 检查容器、服务器 GUID、执行者和执行者用户 ID 是否都有效
                    SendModRPCToServer(MOD_RPC[db.Prefab_ID]["ReturnItemsToPlayer"], self.ServerGUID) -- 发送 RPC 请求到服务器，要求将容器内的物品返还给玩家
                end
            end)
            AddItemBlackListBtn:SetPosition(-365,120) -- 设置按钮的位置
            self:AddChild(AddItemBlackListBtn) -- 将按钮添加到父控件
            table.insert(self.custom_ui_elements,AddItemBlackListBtn) -- 将按钮添加到自定义 UI 元素列表
            --#endregion

            --#region清除白名单的按钮
            local clearItemWhiteListBtn = ImageButton("images/my_futuristic_ui/my_futuristic_ui.xml","hexagonal_down_button_normal.tex","hexagonal_down_button_hover.tex","hexagonal_down_button_disabled.tex","hexagonal_down_button_down.tex",nil,{1,1}) -- 创建一个 ImageButton 用于清除白名单
            clearItemWhiteListBtn:SetHoverText(strings.Btn_ClearWhiteList_ToolTip,{ -- 设置按钮的悬停提示文本
                font = strings.Hover_Text_Font, -- 提示文本字体
                font_size = strings.Hover_Text_Font_Size, -- 提示文本字体大小
                offset_x = 0, -- 提示文本水平偏移
                offset_y = 40, -- 提示文本垂直偏移
                colour =  {1,1,1,1}, -- 提示文本颜色（白色）
            })
            clearItemWhiteListBtn:SetOnClick(function () -- 设置按钮的点击事件回调
                self.ItemWhiteList = {} -- 清空白名单数据表
                WhiteGridList:ResetGrids(self.ItemWhiteList) -- 刷新白名单网格的 UI 显示
                -- BlackGridList:ResetGrids(self.ItemBlackList) -- (注释掉) 清除白名单不影响黑名单显示，无需刷新黑名单
            end)
            --local btn_w,btn_h = clearItemWhiteListBtn:GetSize() -- 获取按钮的宽度和高度
            local clearBtnIcon_1 = Image("images/my_futuristic_ui/my_futuristic_ui.xml", "clean_all.tex") -- 创建一个 Image 控件作为按钮图标
            clearBtnIcon_1:ScaleToSize(29,30) -- 设置图标大小
            clearBtnIcon_1:SetPosition(0,0) -- 设置图标在按钮内的位置（居中）

            clearItemWhiteListBtn:SetPosition(229,-213) -- 设置按钮的位置
            clearItemWhiteListBtn:AddChild(clearBtnIcon_1) -- 将图标添加到按钮内部
            self:AddChild(clearItemWhiteListBtn) -- 将按钮添加到父控件
            table.insert(self.custom_ui_elements,clearItemWhiteListBtn) -- 将按钮添加到自定义 UI 元素列表
            --#endregion

            --#region清除黑名单的按钮
            local clearItemBlackListBtn = ImageButton("images/my_futuristic_ui/my_futuristic_ui.xml","hexagonal_down_button_normal.tex","hexagonal_down_button_hover.tex","hexagonal_down_button_disabled.tex","hexagonal_down_button_down.tex",nil,{1,1}) -- 创建一个 ImageButton 用于清除黑名单
            clearItemBlackListBtn:SetHoverText(strings.Btn_ClearBlackList_ToolTip,{ -- 设置按钮的悬停提示文本
                font = strings.Hover_Text_Font, -- 提示文本字体
                font_size = strings.Hover_Text_Font_Size, -- 提示文本字体大小
                offset_x = 0, -- 提示文本水平偏移
                offset_y = 40, -- 提示文本垂直偏移
                colour =  {1,1,1,1}, -- 提示文本颜色（白色）
            })
            clearItemBlackListBtn:SetOnClick(function () -- 设置按钮的点击事件回调
                self.ItemBlackList = {} -- 清空黑名单数据表
                -- WhiteGridList:ResetGrids(self.ItemWhiteList) -- (注释掉) 清除黑名单不影响白名单显示，无需刷新白名单
                BlackGridList:ResetGrids(self.ItemBlackList) -- 刷新黑名单网格的 UI 显示
            end)
            --btn_w,btn_h = clearItemBlackListBtn:GetSize() -- 获取按钮的宽度和高度
            local clearBtnIcon_2 = Image("images/my_futuristic_ui/my_futuristic_ui.xml", "clean_all.tex") -- 创建一个 Image 控件作为按钮图标
            clearBtnIcon_2:ScaleToSize(29,30) -- 设置图标大小
            clearBtnIcon_2:SetPosition(0,0) -- 设置图标在按钮内的位置（居中）

            clearItemBlackListBtn:SetPosition(-108,-214) -- 设置按钮的位置
            clearItemBlackListBtn:AddChild(clearBtnIcon_2) -- 将图标添加到按钮内部
            self:AddChild(clearItemBlackListBtn) -- 将按钮添加到父控件
            table.insert(self.custom_ui_elements,clearItemBlackListBtn) -- 将按钮添加到自定义 UI 元素列表
            --#endregion

            --#region 添加CollectRule的checkbox的滑动网格
            RuleGridList = self:AddChild(ScrollGridList(
                self.CollectRule, -- 初始数据源为规则字符串表
                function(rules)
                    local rules_data = {} -- 初始化一个空表用于存储转换后的规则数据
                    for _, key in ipairs(ruleKeys) do
                        local value = rules[key] -- 获取规则表中的每个规则值
                        local text = ruleString[key] or key -- 获取规则对应的描述文本，如果没有则使用规则名作为描述
                        if value ~= nil then -- 如果规则值不为 nil
                            table.insert(rules_data, { -- 将规则数据添加到列表中
                                rule_name = key, -- 规则名
                                rule_text = text, -- 规则描述文本
                                rule_value = value -- 规则是否启用（true/false）
                            })
                        end
                    end
                    return rules_data -- 返回转换后的规则数据列表
                end,
                {
                    grid_width = 140, -- 每个网格单元的宽度
                    grid_height = 50, -- 每个网格单元的高度
                    spacing = 0, -- 网格单元之间的间距
                    columns = 1, -- 网格的列数
                    rows = 4, -- 网格的行数
                    peek_percent = 0.5, -- 预览高度占比
                    end_offset = 0.55, -- 结束偏移量（默认为 1）
                    scissor_pad = 10, -- 水平裁剪填充（默认为 10）
                    item_ctor_fn = function (context, index) -- 网格项构造函数
                        local checkbox = CheckBox( -- 创建一个 CheckBox 控件
                            "images/my_futuristic_ui/my_futuristic_ui.xml", -- 图集路径
                            "white_rectangle_checkbox_normal.tex", -- 未选中状态纹理
                            "white_rectangle_checkbox_focus.tex", -- 未选中状态高亮纹理
                            "white_rectangle_checkbox_disabled.tex", -- 未选中状态禁用纹理
                            nil, -- 按下状态纹理 (未使用)
                            {1,1}, -- 缩放比例
                            {0,0}, -- 位置偏移
                            "white_rectangle_checkbox_check_normal.tex", -- 选中状态纹理
                            "white_rectangle_checkbox_check_focus.tex", -- 选中状态高亮纹理
                            "white_rectangle_checkbox_check_disabled.tex", -- 选中状态禁用纹理
                            nil  -- 点击偏移 (使用默认值)
                        )
                        checkbox.ruleText = Text(strings.Rule_And_Mode_Font, strings.Rule_And_Mode_Font_Size) -- 创建一个 Text 控件用于显示规则描述
                        checkbox:AddChild(checkbox.ruleText) -- 将文本控件添加到复选框内部
                        return checkbox -- 返回创建的 CheckBox 控件
                    end,
                    apply_fn = function (context, checkbox, item, index) -- 应用函数
                        if item then -- 如果有数据项
                            checkbox:SetToggle(self.CollectRule[item.rule_name] or false, false) -- 设置复选框的初始状态，false 表示不触发回调
                            checkbox:SetOnToggle(function (checked) -- 设置复选框状态切换时的回调函数
                                self.CollectRule[item.rule_name] = checked -- 更新收集规则表中的对应规则状态
                        end)
                        checkbox.ruleText:SetAutoSizingString(item.rule_text,125,true) -- 设置规则描述文本内容并自动调整大小
                        checkbox.ruleText:SetColour(1, 1, 1, 1) -- 设置文本颜色为白色
                        checkbox.ruleText:SetRegionSize(125, 50) -- 设置文本区域大小
                        checkbox.ruleText:SetVAlign(ANCHOR_MIDDLE) -- 设置垂直对齐方式为居中
                        checkbox.ruleText:SetHAlign(ANCHOR_MIDDLE) -- 设置水平对齐方式为居中
                        checkbox:SetHoverText(item.rule_text, { -- 设置复选框的悬停提示文本
                            font = strings.Hover_Text_Font, -- 提示文本字体
                            font_size = strings.Hover_Text_Font_Size, -- 提示文本字体大小
                            offset_x = 0, -- 提示文本水平偏移
                            offset_y = 40, -- 提示文本垂直偏移
                            colour = {1,1,1,1}, -- 提示文本颜色（白色）
                        })
                        checkbox:Show() -- 显示复选框
                        else
                            checkbox:Hide() -- 如果没有数据项，则隐藏复选框
                        end
                    end,
                    scrollbar_offset = 25, -- 设置滚动条的水平偏移量，默认为30
                    scrollbar_vertical_offset = 0, -- 设置滚动条的垂直偏移量，默认为0
                    scrollbar_height_offset = -30, -- 设置滚动条的高度的变化值，默认-60(相对于滚动列表的高度减少-60)
                    scrollbar_style = -- 滚动条样式配置
                    {
                        atlas = "images/my_futuristic_ui/my_futuristic_ui.xml", -- 滚动条使用的图集
                        up_arrow = "white_scrollbar_arrow_up.tex", -- 向上箭头纹理
                        up_arrow_scale = 0.18, -- 向上箭头缩放比例
                        down_arrow = "white_scrollbar_arrow_down.tex", -- 向下箭头纹理
                        down_arrow_scale = 0.18, -- 向下箭头缩放比例
                        bar = "white_scrollbar_bar.tex", -- 滚动条背景条纹理
                        bar_width = 15, -- 滚动条背景条宽度
                        bar_height = 160, -- 滚动条背景条高度
                        handle = "white_scrollbar_handle.tex", -- 滚动条滑块纹理
                        handle_scale = 0.20, -- 滑块缩放比例
                    }
                }
            ))
            RuleGridList:SetPosition(430, 123) -- 设置规则网格列表的位置
            table.insert(self.custom_ui_elements, RuleGridList) -- 将规则网格列表添加到自定义 UI 元素列表
            --#endregion

            --#region 添加CollectMode的checkbox的滑动网格
            ModeGridList = self:AddChild(ScrollGridList(
                self.CollectMode, -- 模式字符串表
                function(modes)
                    local modes_data = {} -- 初始化一个空表用于存储转换后的模式数据
                    for _, key in ipairs(modeKeys) do
                        local value = modes[key] -- 获取模式表中的每个模式值
                        local text = modeString[key] or key -- 获取模式对应的描述文本，如果没有则使用模式名作为描述
                        if value ~= nil then -- 如果模式值不为 nil
                            table.insert(modes_data, { -- 将模式数据添加到列表中
                                mode_name = key, -- 模式名
                                mode_text = text, -- 模式描述文本
                                mode_value = value -- 模式是否启用（true/false）
                            })
                        end
                    end
                    return modes_data -- 返回转换后的模式数据列表
                end,
                {
                    grid_width = 140, -- 每个网格单元的宽度
                    grid_height = 50, -- 每个网格单元的高度
                    spacing = 0, -- 网格单元之间的间距
                    columns = 1, -- 网格的列数
                    rows = 4, -- 网格的行数
                    peek_percent = 0.5, -- 预览高度占比
                    end_offset = 1, -- 结束偏移量（默认为 1）
                    scissor_pad = 10, -- 水平裁剪填充（默认为 10）
                    item_ctor_fn = function (context, index) -- 网格项构造函数
                        local checkbox = CheckBox( -- 创建一个 CheckBox 控件
                            "images/my_futuristic_ui/my_futuristic_ui.xml", -- 图集路径
                            "red_rectangle_checkbox_normal.tex", -- 未选中状态纹理
                            "red_rectangle_checkbox_focus.tex", -- 未选中状态高亮纹理
                            "red_rectangle_checkbox_disabled.tex", -- 未选中状态禁用纹理
                            nil, -- 按下状态纹理 (未使用)
                            {1,1}, -- 缩放比例
                            {0,0}, -- 位置偏移
                            "red_rectangle_checkbox_check_normal.tex", -- 选中状态纹理
                            "red_rectangle_checkbox_check_focus.tex", -- 选中状态高亮纹理
                            "red_rectangle_checkbox_check_disabled.tex", -- 选中状态禁用纹理
                            nil  -- 点击偏移 (使用默认值)
                        )
                        checkbox.ruleText = Text(strings.Rule_And_Mode_Font, strings.Rule_And_Mode_Font_Size) -- 创建一个 Text 控件用于显示规则描述
                        checkbox:AddChild(checkbox.ruleText) -- 将文本控件添加到复选框内部
                        return checkbox -- 返回创建的 CheckBox 控件
                    end,
                    apply_fn = function (context, checkbox, item, index) -- 应用函数
                        if item then -- 如果有数据项
                            checkbox:SetToggle(self.CollectMode[item.mode_name] or false, false) -- 设置复选框的初始状态，false 表示不触发回调
                            checkbox:SetOnToggle(function (checked) -- 设置复选框状态切换时的回调函数
                                self.CollectMode[item.mode_name] = checked -- 更新收集规则表中的对应规则状态
                        end)
                        checkbox.ruleText:SetAutoSizingString(item.mode_text,125,true) -- 设置模式描述文本内容并自动调整大小
                        checkbox.ruleText:SetColour(1, 1, 1, 1) -- 设置文本颜色为白色
                        checkbox.ruleText:SetRegionSize(125, 50) -- 设置文本区域大小
                        checkbox.ruleText:SetVAlign(ANCHOR_MIDDLE) -- 设置垂直对齐方式为居中
                        checkbox.ruleText:SetHAlign(ANCHOR_MIDDLE) -- 设置水平对齐方式为居中
                        checkbox:SetHoverText(item.mode_text, { -- 设置复选框的悬停提示文本
                            font = strings.Hover_Text_Font, -- 提示文本字体
                            font_size = strings.Hover_Text_Font_Size, -- 提示文本字体大小
                            offset_x = 0, -- 提示文本水平偏移
                            offset_y = 40, -- 提示文本垂直偏移
                            colour = {1,1,1,1}, -- 提示文本颜色（白色）
                        })
                        checkbox:Show() -- 显示复选框
                        else
                            checkbox:Hide() -- 如果没有数据项，则隐藏复选框
                        end
                    end
                }
            ))
            ModeGridList:SetPosition(429, -125) -- 设置模式网格列表的位置
            table.insert(self.custom_ui_elements, ModeGridList) -- 将模式网格列表添加到自定义 UI 元素列表
            --#endregion

            --#region 添加保存按钮，保存的时候进行数据同步
            local SaveAndSync_Btn = ImageButton("images/my_futuristic_ui/my_futuristic_ui.xml","hexagonal_up_button_normal.tex","hexagonal_up_button_hover.tex","hexagonal_up_button_disabled.tex","hexagonal_up_button_down.tex",nil,{1,1}) -- 创建一个 ImageButton 用于保存并同步设置
            SaveAndSync_Btn:SetHoverText(strings.Btn_SaveAndSync_ToolTip,{ -- 设置按钮的悬停提示文本
                font = strings.Hover_Text_Font, -- 提示文本字体
                font_size = strings.Hover_Text_Font_Size, -- 提示文本字体大小
                offset_x = 0, -- 提示文本水平偏移
                offset_y = 40, -- 提示文本垂直偏移
                colour =  {1,1,1,1}, -- 提示文本颜色（白色）
            })
            SaveAndSync_Btn:SetOnClick(function () -- 设置按钮的点击事件回调
                container:UpdateWhiteList(self.ItemWhiteList) -- 调用容器的 UpdateWhiteList 方法，将当前客户端的白名单数据发送到服务器
                container:UpdateBlackList(self.ItemBlackList) -- 调用容器的 UpdateBlackList 方法，将当前客户端的黑名单数据发送到服务器
                container:UpdateCollectRule(self.CollectRule) -- 调用容器的 UpdateCollectRule 方法，将当前客户端的收集规则数据发送到服务器
                container:UpdateCollectMode(self.CollectMode) -- 调用容器的 UpdateCollectMode 方法，将当前客户端的收集模式数据发送到服务器
            end)
            -- self:AddChild(SaveAndSync_Btn) -- (注释掉) 按钮将在添加图标后再次添加
            --btn_w,btn_h = SaveAndSync_Btn:GetSize() -- 获取按钮的宽度和高度
            local saveBtnIcon = Image("images/my_futuristic_ui/my_futuristic_ui.xml", "save_icon.tex") -- 创建保存图标 Image 控件
            saveBtnIcon:ScaleToSize(30,33) -- 缩放图标大小
            saveBtnIcon:SetPosition(0,0) -- 设置图标在按钮内的位置（居中）

            SaveAndSync_Btn:SetPosition(-500,300) -- 设置保存按钮的位置
            SaveAndSync_Btn:AddChild(saveBtnIcon) -- 将保存图标添加到按钮内部
            self:AddChild(SaveAndSync_Btn) -- 将带有图标的保存按钮添加到父控件
            table.insert(self.custom_ui_elements,SaveAndSync_Btn) -- 将保存按钮添加到自定义 UI 元素列表
            --#endregion

            --#region 添加关闭按钮，关闭的时候不进行数据同步
            local Close_Btn = ImageButton("images/my_futuristic_ui/my_futuristic_ui.xml","hexagonal_up_button_normal.tex","hexagonal_up_button_hover.tex","hexagonal_up_button_disabled.tex","hexagonal_up_button_down.tex",nil,{1,1}) -- 创建一个 ImageButton 用于关闭界面（不保存）
            Close_Btn:SetHoverText(strings.Btn_Close_ToolTip,{ -- 设置按钮的悬停提示文本
                font = strings.Hover_Text_Font, -- 提示文本字体
                font_size = strings.Hover_Text_Font_Size, -- 提示文本字体大小
                offset_x = 0, -- 提示文本水平偏移
                offset_y = 40, -- 提示文本垂直偏移
                colour =  {1,1,1,1}, -- 提示文本颜色（白色）
            })
            Close_Btn:SetOnClick(function () -- 设置按钮的点击事件回调
                -- container:UpdateWhiteList(self.ItemWhiteList) -- (注释掉) 关闭时不主动同步白名单
                -- container:UpdateBlackList(self.ItemBlackList) -- (注释掉) 关闭时不主动同步黑名单
                -- container:UpdateCollectRule(self.CollectRule) -- (注释掉) 关闭时不主动同步收集规则
                if container and container.replica and container.replica.container then -- 检查容器及其 replica 和 container 组件是否存在
                    --if container.replica.container._isopen then -- 检查容器是否处于打开状态(为了兼容独行长路注释掉了，但是貌似本身就没有必要有这一行)
                        SendModRPCToServer(MOD_RPC[db.Prefab_ID]["CloseContainer"], self.ServerGUID) -- 发送 RPC 到服务器，通知服务器容器已被客户端关闭（可能用于解锁）
                        container.replica.container:Close() -- 调用容器 replica 的 Close 方法来关闭界面
                    --end
                end
            end)
            -- self:AddChild(Close_Btn) -- (注释掉) 按钮将在添加图标后再次添加
            --btn_w,btn_h = Close_Btn:GetSize() -- 获取按钮的宽度和高度
            local closeBtnIcon = Image("images/my_futuristic_ui/my_futuristic_ui.xml", "no_icon.tex") -- 创建关闭图标 Image 控件
            closeBtnIcon:ScaleToSize(30,30) -- 缩放图标大小
            closeBtnIcon:SetPosition(0,0) -- 设置图标在按钮内的位置（居中）

            Close_Btn:SetPosition(500,300) -- 设置关闭按钮的位置
            Close_Btn:AddChild(closeBtnIcon) -- 将关闭图标添加到按钮内部
            self:AddChild(Close_Btn) -- 将带有图标的关闭按钮添加到父控件
            table.insert(self.custom_ui_elements,Close_Btn) -- 将关闭按钮添加到自定义 UI 元素列表
            --#endregion
            
            --#region 为了以防万一槽位内有物品导致tile没有隐藏的问题
            HideSpecialItemBg() -- 调用隐藏特殊物品背景的函数
            --#endregion

            --#region 预设界面
            
            --#region 预设界面背景
            local Preset_widget = Widget("preset_widget")
            self:AddChild(Preset_widget)
            Preset_widget:MoveToBack()
            Preset_widget:SetPosition(415,0,0)
            Preset_widget.bganim = Preset_widget:AddChild(UIAnim())
            Preset_widget.bganim:GetAnimState():SetBank('preset_widget')
            Preset_widget.bganim:GetAnimState():SetBuild('preset_widget')
            Preset_widget.bganim:GetAnimState():PlayAnimation('open')
            Preset_widget.status = "Hide" --代表此时预设界面是隐藏在常规界面后面的
            --#endregion

            --#region 预设界面标题
            local Preset_Title = Preset_widget:AddChild(Text(strings.Preset_Title_Font, strings.Preset_Title_Font_Size + 10, strings.Preset_Title, {1,1,1,1}))
            Preset_widget:AddChild(Preset_Title) -- 将标题添加到预设界面
            Preset_Title:SetPosition(-39, 220, 0) -- 设置标题位置
            Preset_Title:SetHAlign(ANCHOR_LEFT) -- 设置标题水平对齐方式为左对齐
            Preset_Title:SetVAlign(ANCHOR_MIDDLE) -- 设置标题垂直对齐方式为中间对齐
            --#endregion

            --#region 红色侧边按钮
            local Side_Btn = Preset_widget:AddChild(ImageButton("images/my_futuristic_ui/my_futuristic_ui.xml","side_button_normal.tex","side_button_hover.tex","side_button_disabled.tex","side_button_down.tex",nil,{1,1}))
            Side_Btn:SetPosition(171,0,0)
            Side_Btn:SetOnClick(function ()
                if Preset_widget.status == "Moving" then
                    return --界面正在移动，请勿重复点击
                end
                Side_Btn.inst:StartThread(function ()
                    local start_time = GetTime()
                    if Preset_widget.status == "Hide" then
                        Preset_widget.status = "Moving"
                        while self do
                            local over_time = GetTime() - start_time
                            local x = 0

                            if over_time < 0.35 then
                                -- 0 - 0.35s: 从 0 加速到 115（平方加速）
                                local t = over_time / 0.35
                                x = 115 * t * t  -- 平方加速

                            elseif over_time < 0.4 then
                                -- 0.35s - 0.4s: 保持在 115
                                x = 115

                            elseif over_time < 0.45 then
                                -- 0.4s - 0.45s: 从 115 减速下降到 106（平方减速）
                                local t = (over_time - 0.4) / 0.05
                                x = 115 - (115 - 106) * (t * t)  -- 平方减速

                            else
                                -- 最终定位
                                self:SetPosition(Vector3(-106, 0, 0))
                                Preset_widget:SetPosition(Vector3(415, 0, 0) - Vector3(-106 * 2.0 * 5.0 / 3.0, 0, 0))
                                Preset_widget.status = "Show"
                                break
                            end

                            -- 实时更新位置
                            self:SetPosition(Vector3(-x, 0, 0))
                            Preset_widget:SetPosition(Vector3(415, 0, 0) - Vector3(-x * 2.0 * 5.0 / 3.0, 0, 0))

                            Sleep(FRAMES * GetTickTime()) -- 控制帧率同步
                        end
                    elseif Preset_widget.status == "Show" then
                        Preset_widget.status = "Moving"
                        while self do
                            local over_time = GetTime() - start_time
                            local x = 106 -- 初始位置

                            if over_time < 0.3 then
                                -- 0 - 0.3s: 从 106 减速下降到 0（平方减速）
                                local t = over_time / 0.3
                                x = 106 * (1 - t * t)  -- 平方减速公式
                            else
                                -- 最终归位
                                x = 0
                                self:SetPosition(Vector3(-x, 0, 0))
                                Preset_widget:SetPosition(Vector3(415, 0, 0))
                                Preset_widget.status = "Hide"
                                break
                            end

                            -- 实时更新位置
                            self:SetPosition(Vector3(-x, 0, 0))
                            Preset_widget:SetPosition(Vector3(415, 0, 0) - Vector3(-x * 2.0 * 5.0 / 3.0, 0, 0))

                            Sleep(FRAMES * GetTickTime()) -- 控制帧率同步
                        end
                    end
                end)
            end)
            --#endregion

            --#region 预设列表
            PresetList = Preset_widget:AddChild(ScrollGridList(
                db.PresetData.list, -- 使用数据库中的预设数据
                function(presets)
                    local presets_data = {} -- 初始化一个空表用于存储转换后的预设数据
                    for _, preset_name in ipairs(db.PresetData.order) do
                        local preset = presets[preset_name]
                        if preset then
                            table.insert(presets_data, {
                                name = preset.name,
                                description = preset.description,
                            })
                        end
                    end
                    return presets_data -- 返回转换后的预设数据列表
                end,
                {
                    grid_width = 268, -- 每个网格单元的宽度
                    grid_height = 125, -- 每个网格单元的高度
                    spacing = 0, -- 网格单元之间的间距
                    columns = 1, -- 网格的列数
                    rows = 3, -- 网格的行数
                    peek_percent = 0, -- 预览高度占比
                    end_offset = 1, -- 结束偏移量（默认为 1）
                    scissor_pad = 10, -- 水平裁剪填充（默认为 10）
                    item_ctor_fn = function (context, index) -- 网格项构造函数
                        local imgbtn = ImageButton("images/my_futuristic_ui/my_futuristic_ui.xml", "preset_button_normal.tex", "preset_button_hover.tex", "preset_button_disabled.tex", "preset_button_down.tex", nil, {1,1}) -- 创建 ImageButton
                        imgbtn.title = imgbtn:AddChild(Text(strings.Preset_Title_Font, strings.Preset_Title_Font_Size)) -- 添加标题文本
                        imgbtn.title:SetPosition(0, 30, 0) -- 设置标题文本位置
                        imgbtn.title:SetHAlign(ANCHOR_MIDDLE) -- 设置标题文本水平对齐方式为居中
                        imgbtn.title:SetColour(1, 1, 0, 1) --设置为黄色

                        imgbtn.desc = imgbtn:AddChild(Text(strings.Preset_Desc_Font, strings.Preset_Desc_Font_Size)) -- 添加描述文本
                        imgbtn.desc:SetPosition(0,-20,0)
                        imgbtn.desc:SetHAlign(ANCHOR_LEFT) -- 设置描述文本水平对齐方式为左对齐
                        imgbtn.desc:SetVAlign(ANCHOR_MIDDLE) -- 设置描述文本垂直对齐方式为居中
                        imgbtn.desc:SetColour(1, 0, 0, 1) -- 设置描述文本颜色为红色
                        imgbtn.desc:SetRegionSize(235, 60)
                        imgbtn.desc:EnableWordWrap(true)
                        return imgbtn -- 返回 ImageButton
                    end,
                    apply_fn = function (context, imgbtn, item, index) -- 应用函数
                        if item then -- 如果有数据项
                            imgbtn.title:SetString(item.name) -- 设置标题文本
                            imgbtn.desc:SetString(item.description) -- 设置描述文本
                            imgbtn:SetHoverText(item.description,{
                                font = strings.Hover_Text_Font,
                                font_size = strings.Hover_Text_Font_Size,
                                region_h = 60,
                                region_w = 180,
                                wordwrap = true,
                                offset_x = 0,
                                offset_y = 120,
                                colour = {1, 1, 1, 1}
                            })
                            imgbtn.hovertext:SetHAlign(ANCHOR_LEFT)

                            imgbtn:SetOnClick(function () -- 设置按钮的点击事件回调
                                LoadPreset(item.name) -- 调用容器的 LoadPreset 方法加载选中的预设
                            end)
                            local old_OnControl = imgbtn.OnControl -- 保存原有的 OnControl 方法
                            imgbtn.OnControl = function(self,control,down)
                                --右键点击事件回调
                                if control == CONTROL_SECONDARY and down then
                                    --print("[DEBUG] Right click on preset: " .. item.name) -- 调试输出，表明右键点击了预设
                                    TheFrontEnd:PushScreen(
                                        PopupDialogScreen(
                                            strings.Preset_Delete_Title, --删除预设的标题
                                            string.format(strings.Preset_Delete_Content, item.name),
                                            {},
                                            2,
                                            {
                                                cancel = {
                                                    scale = {0.8, 0.4},
                                                    text_scale = {1.25, 2.5},
                                                    text = STRINGS.UI.CUSTOMIZATIONSCREEN.BACK,
                                                    cb = function()
                                                        --TheFrontEnd:PopScreen()
                                                    end,
                                                },
                                                confirm = {
                                                    scale = {0.8, 0.4},
                                                    text_scale = {1.25, 2.5},
                                                    text = STRINGS.UI.CUSTOMIZATIONSCREEN.DELETE,
                                                    cb = function()
                                                        RemovePreset(item.name) -- 调用 RemovePreset 函数删除选中的预设
                                                    end,
                                                }
                                            }
                                        )
                                    )
                                    return true -- 返回 true 表示事件已处理
                                end
                                return old_OnControl(self, control, down) -- 调用原有的 OnControl 方法
                            end
                            imgbtn:Show() -- 显示按钮
                        else
                            imgbtn:Hide() -- 如果没有数据项，隐藏按钮
                        end
                    end,
                    scrollbar_offset = 25, -- 设置滚动条的水平偏移量，默认为30
                    scrollbar_vertical_offset = 0, -- 设置滚动条的垂直偏移量，默认为0
                    scrollbar_height_offset = -40, -- 设置滚动条的高度的变化值，默认-60(相对于滚动列表的高度减少-60)
                    scrollbar_style = -- 滚动条样式配置
                    {
                        atlas = "images/my_futuristic_ui/my_futuristic_ui.xml", -- 滚动条使用的图集
                        up_arrow = "white_scrollbar_arrow_up.tex", -- 向上箭头纹理
                        up_arrow_scale = 0.2, -- 向上箭头缩放比例
                        down_arrow = "white_scrollbar_arrow_down.tex", -- 向下箭头纹理
                        down_arrow_scale = 0.2, -- 向下箭头缩放比例
                        bar = "white_scrollbar_bar.tex", -- 滚动条背景条纹理
                        bar_width = 20, -- 滚动条背景条宽度
                        bar_height = 300, -- 滚动条背景条高度
                        handle = "white_scrollbar_handle.tex", -- 滚动条滑块纹理
                        handle_scale = 0.25, -- 滑块缩放比例
                    }
                }
            ))
            Preset_widget:AddChild(PresetList) -- 将预设列表添加到预设界面
            PresetList:SetPosition(-39, -58, 0) -- 设置预设列表的位置
            --#endregion

            --#region 添加预设按钮
            local AddPreset_Btn = Preset_widget:AddChild(ImageButton("images/my_futuristic_ui/my_futuristic_ui.xml","add_preset_button_normal.tex","add_preset_button_hover.tex","add_preset_button_disabled.tex","add_preset_button_down.tex",nil,{1,1}))
            AddPreset_Btn:SetPosition(-39,162,0)
            AddPreset_Btn:SetHoverText(strings.Btn_AddPreset_ToolTip,{ -- 添加预设按钮的悬停提示文本
                font = strings.Hover_Text_Font, -- 提示文本字体
                font_size = strings.Hover_Text_Font_Size, -- 提示文本字体大小
                offset_x = 0, -- 提示文本水平偏移
                offset_y = 40, -- 提示文本垂直偏移
            })
            AddPreset_Btn:SetOnClick(function ()
                TheFrontEnd:PushScreen(NamePresetScreen(
                strings.Preset_Title,
                STRINGS.UI.CUSTOMIZATIONSCREEN.SAVEPRESET,
                function (name,description)
                    AddPreset(name, description) -- 调用 AddPreset 函数保存预设，同时刷新界面
                end
                ))
            end)
            --#endregion

            table.insert(self.custom_ui_elements, Preset_widget)
            --#endregion

        end -- 结束 `if container.prefab == db.Prefab_ID then` 的判断
    end -- 结束重写的 Open 方法
    
    function self:Close() -- 重写 Close 方法
        -- 立即清理自定义按钮
        print("[DEBUG] Widget Close called") -- 调试输出，表明 Close 方法被调用
        for _, ui_element in ipairs(self.custom_ui_elements) do -- 遍历所有存储的自定义 UI 元素
            ui_element:Kill() -- 销毁 UI 元素，释放资源并从界面移除
        end
        self.custom_ui_elements = {} -- 清空自定义 UI 元素列表 (虽然元素已 Kill，清空列表是个好习惯)
        
        -- 关闭时进行数据同步 (这部分逻辑似乎与关闭按钮的逻辑重复且可能冲突，需要注意)
        if self.container ~= nil then -- 检查 self.container 是否存在 (Open 时被赋值)
            if self.container.prefab == db.Prefab_ID then -- 检查是否是本模组的特定容器
                -- self.container:UpdateWhiteList(self.ItemWhiteList) -- (注释掉) 默认关闭时不进行数据同步
                -- self.container:UpdateBlackList(self.ItemBlackList) -- (注释掉) 默认关闭时不进行数据同步
                -- self.container:UpdateCollectRule(self.CollectRule) -- (注释掉) 默认关闭时不进行数据同步
                -- 将物品返还给玩家
                if self.container and self.ServerGUID  then -- 再次检查容器和 ServerGUID 是否存在
                    SendModRPCToServer(MOD_RPC[db.Prefab_ID]["ReturnItemsToPlayer"], self.ServerGUID) -- 发送 RPC 请求到服务器，要求返还物品（确保玩家不会因关闭界面丢失放入的物品）
                end
            end
        end
        _Close(self) -- 调用原始的 Close 方法，执行默认的关闭逻辑
    end -- 结束重写的 Close 方法

    function self:OnItemGet(data) --重写获取物品方法，关闭物品放在槽位内的时候的新鲜度显示
        _OnItemGet(self,data) -- 调用原始的 OnItemGet 方法，执行默认的物品获取逻辑
        if self.container and self.container.prefab == db.Prefab_ID and self.inv then -- 检查容器是否是本模组的特定容器
            for _, v in pairs(self.inv) do -- 遍历所有物品槽位
                if v.tile then -- 如果槽位有 tile 属性
                    if v.tile.spoilage then -- 如果槽位有 spoilage 属性
                        v.tile.spoilage:Hide() -- 隐藏 spoilage 组件
                    end
                    if v.tile.wetness then -- 如果槽位有 wetness 属性
                        v.tile.wetness:Hide() -- 隐藏湿度组件
                    end
                    if v.tile.rechargeframe then -- 如果槽位有 rechargeframe 属性
                        v.tile.rechargeframe:Hide() -- 隐藏充能框架组件
                    end
                    if v.tile.recharge then -- 如果槽位有 recharge 属性
                        v.tile.recharge:Hide() -- 隐藏充能组件
                    end
                    if v.tile.bg then -- 如果槽位有 bg 属性
                        v.tile.bg:Hide() -- 隐藏 bg 组件
                    end
                end
            end
        end
    end

end) -- 结束 AddClassPostConstruct
